#include "stdafx.h"
#include "CppUnitTest.h"

#include <SnakeLib/BoardCodec.h>
#include <SnakeLib/Problem.h>

#include "MySolver/MySolver.h"

#include "SnakeAssert.h"

//using namespace mstest = Microsoft::VisualStudio::CppUnitTestFramework;
using namespace snake;

namespace MySolverTests
  {		
  TEST_CLASS(MySolverSuite)
    {
    public:

      //TEST_METHOD(Should_When_)
      //  {
      //  // Arrange
      //  auto board =           
      //    "+--+"
      //    "|! |"
      //    "|> |"
      //    "+--+";
      //  EDirection expected = UP;

      //  // Act, Assert
      //  Assert::Solve(board, MySolver(), expected);
      //  }

      TEST_METHOD(ShouldGoLeftWhenBottomWall)
        {
        // arrange
        auto board =           
          "+---+"
          "|   |"
          "|   |"
          "| v |"
          "+---+";
        EDirection expected = LEFT;

        // act, assert
        snake::Assert::Solve(board, MySolver(), expected);
        }

      TEST_METHOD(ShouldGoUpWhenLeftWall)
        {
        // arrange
        auto board =           
          "+---+"
          "|   |"
          "|   |"
          "|<  |"
          "+---+";
        EDirection expected = UP;

        // act, assert
        snake::Assert::Solve(board, MySolver(), expected);
        }

      TEST_METHOD(ShouldGoRightWhenUpperWall)
        {
        // arrange
        auto board =           
          "+---+"
          "|^  |"
          "|   |"
          "|   |"
          "+---+";
        EDirection expected = RIGHT;

        // act, assert
        snake::Assert::Solve(board, MySolver(), expected);
        }

      TEST_METHOD(ShouldGoDownWhenRightWall)
        {
        // arrange
        auto board =           
          "+---+"
          "|  >|"
          "|   |"
          "|   |"
          "+---+";
        EDirection expected = DOWN;

        // act, assert
        snake::Assert::Solve(board, MySolver(), expected);
        }

      TEST_METHOD(ShouldGetSnakeInfo)
        {
        // Arrange
        BoardCodec board_codec;

        auto board_down_2_3 =           
          "+---+"
          "|   |"
          "|   |"
          "| v |"
          "+---+";
        snake::Problem problem_down(board_codec.FromString(board_down_2_3));

        auto board_left_3_1 =           
          "+---+"
          "|  <|"
          "|   |"
          "|   |"
          "+---+";
        snake::Problem problem_left(board_codec.FromString(board_left_3_1));

        auto board_up_1_2 =           
          "+---+"
          "|   |"
          "|^  |"
          "|   |"
          "+---+";
        snake::Problem problem_up(board_codec.FromString(board_up_1_2));

        auto board_right_2_2 =           
          "+---+"
          "|   |"
          "| > |"
          "|   |"
          "+---+";
        snake::Problem problem_right(board_codec.FromString(board_right_2_2));


        auto expected_down_2_3 = SnakeInfo();
        expected_down_2_3.m_head_coord.first = 2;
        expected_down_2_3.m_head_coord.second = 3;
        expected_down_2_3.m_direction = EDirection::DOWN;

        auto expected_left_3_1 = SnakeInfo();
        expected_left_3_1.m_head_coord.first = 3;
        expected_left_3_1.m_head_coord.second = 1;
        expected_left_3_1.m_direction = EDirection::LEFT;

        auto expected_up_1_2 = SnakeInfo();
        expected_up_1_2.m_head_coord.first = 1;
        expected_up_1_2.m_head_coord.second = 2;
        expected_up_1_2.m_direction = EDirection::UP;

        auto expected_right_2_2 = SnakeInfo();
        expected_right_2_2.m_head_coord.first = 2;
        expected_right_2_2.m_head_coord.second = 2;
        expected_right_2_2.m_direction = EDirection::RIGHT;

        // Act
        auto actual_down_2_3 = GetSnakeInfo(problem_down.GetBoard());
        auto actual_left_3_1 = GetSnakeInfo(problem_left.GetBoard());
        auto actual_up_1_2 = GetSnakeInfo(problem_up.GetBoard());
        auto actual_right_2_2 = GetSnakeInfo(problem_right.GetBoard());

        // Assert
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::IsTrue(expected_down_2_3 == actual_down_2_3);
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::IsTrue(expected_up_1_2 == actual_up_1_2);
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::IsTrue(expected_left_3_1 == actual_left_3_1);
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::IsTrue(expected_right_2_2 == actual_right_2_2);
        }

      TEST_METHOD(ShouldGetFoodPosition)
        {
        // Arrange
        BoardCodec board_codec;

        auto board1 =           
          "+---+"
          "|   |"
          "| ! |"
          "|   |"
          "+---+";
        snake::Problem problem1(board_codec.FromString(board1));

        auto board2 =           
          "+---+"
          "|  !|"
          "|   |"
          "|   |"
          "+---+";
        snake::Problem problem2(board_codec.FromString(board2));

        auto expected1 = TCoord(2, 2);
        auto expected2 = TCoord(3, 1);
        // Act

        auto actual1 = GetFoodCoord(problem1.GetBoard());
        auto actual2 = GetFoodCoord(problem2.GetBoard());
        // Assert

        Microsoft::VisualStudio::CppUnitTestFramework::Assert::AreEqual(expected1.first, actual1.first);
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::AreEqual(expected1.second, actual1.second);
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::AreEqual(expected2.first, actual2.first);
        Microsoft::VisualStudio::CppUnitTestFramework::Assert::AreEqual(expected2.second, actual2.second);
        }
    };
  }